/* ###################################################################
**     Filename    : main.c
**     Processor   : S32K14x
**     Abstract    :
**         Main module.
**         This module contains user's application code.
**     Settings    :
**     Contents    :
**         No public methods
**
** ###################################################################*/
/*!
** @file main.c
** @version 01.00
** @brief
**         Main module.
**         This module contains user's application code.
*/
/*!
**  @addtogroup main_module main module documentation
**  @{
*/
/* MODULE main */


/* Including necessary module. Cpu.h contains other modules needed for compiling.*/
#include "Cpu.h"

volatile int exit_code = 0;

/* User includes (#include below this line is not maintained by Processor Expert) */

#include "load.h"
#include "CAN_Communication.h"

#include "Config.h"    /* the configuration header file*/

uint8_t STATE;          /*bootloader state machine*/
uint8_t pSln;           /*S-record line buffer pointer*/
uint8_t Sline[128];     /*S-record line buffer for temp store the received S-record from CAN bus*/

void app_entry(void)
{
	(*(void (*)(void))(APP_StartAddr))();/*run the function via function pointer convert with a certain address*/

	while(1);/*stop here for anyhow*/
}

/* the FLASH SSD configuration structure pointer */
flash_ssd_config_t pSSDConfig;


 /*FUNCTION**********************************************************************
  *
  * Function Name : NVM_Init
  * Description   : Initialize the MCU NVM resource, including P-Flash and FlexNVM(EEE)
  *
  * Implements    : NVM_Init_Activity
  *END**************************************************************************/
 status_t NVM_Init(void)
 {
	 status_t ret = STATUS_SUCCESS;

	/*
	* initialize the FLASH module/driver
	*/
	 ret = FLASH_DRV_Init(&Flash1_InitConfig0, &pSSDConfig);


	 return ret;
 }

/*!
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
int main(void)
{
  /* Write your local variable definition here */

	uint32_t i;                    	/* Index */

	uint32_t Srecord_address = 0;;   /*used to store S-Record line address */
	uint8_t Srecord_FLASH_line = 0;  /* flag of Flash line */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */
  /* For example: for(;;) { } */

    /*
     * initialize the system clock and peripheral clock
     */
    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0,CLOCK_MANAGER_POLICY_FORCIBLE);

    /*
     * initialize the GPIO for CAN and indication RGB LED
     */
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

    /*
     * initialize the CAN communication for bootloader
     */
    CAN_CommunicationInit();

    /* Disable cache to ensure that all flash operations will take effect instantly,
     * this is device dependent */
#ifndef FLASH_TARGET
#ifdef S32K144_SERIES

    /* All speculation disabled and speculation buffer is cleared */
    MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x3u); /*P-Flash*/
    MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x3u); /*Data-Flash*/

#endif /* S32K144_SERIES */
#endif /* FLASH_TARGET */

    /***********************************************************************
	 * wait 500ms for bootlader link request from host
	 ***********************************************************************/
	for(i=0; i<500; i++)
	{
		if((CAN_BufferReceive_Flag!=0)&&(CAN_RxMsg->data[0]==DOWN_LINK))
		{
			/* respond the PC terminal */
			RcvDtProc();

			CAN_BufferReceive_Flag = 0;    /*reset the CAN received flag*/
			STATE = _STA_LINKED;    	   /*set bootloader state machine as linked for bootloader loop entry*/

			break;
		}
		else
		{
			OSIF_TimeDelay(1);     /*delay 1ms per cycle*/
		}
	}

	if (STATE == _STA_NOT_LINKED)  /* no bootloader link request during last 500ms */
	{

		Prepare_Before_Jump();    /*de-initialize the used peripherals and clean RAM*/

		app_entry();              /* jump to app and should not back   */
		for(;;) ;                 /* stop here however in case run away */
	}

	/* respond the PC terminal */
	RcvDtProc();
	StatusAck(UP_READY);    /*feed back ready for receive new data download*/

	pSln = 0;               /*point to the position of a S-Record with a line */

    while(1)
    {
    	if(CAN_BufferReceive_Flag)       /*is new CAN data received*/
		{
			/* respond the PC terminal */
			RcvDtProc();
			CAN_BufferReceive_Flag = 0;  /*clean the new CAN data received flag for new data*/

			switch (CAN_RxMsg->data[0])
			{
				case DOWN_LINK:               /* still possible, since DownloadID < UploadID */
					StatusAck(UP_READY);      /*feed back ready for receive new data download*/
					break;

				case DOWN_LINE_END:           /* completed a line of Srecord receive*/
					StatusAck(UP_BUSY);       /*feed back busy for process, and PC terminal stop download data*/
					if(SPASS==SRcdCvt(&Sline[0], &srcd)) /*convert and S-record line is OK for bootloader*/
					{
					  Srecord_address = srcd.addr; /*get the S-record line address*/
					  if(RAM_RANGE_CHECK(Srecord_address))
					  {
						 SrcdProg_RAM(&srcd);   /*write the received data into RAM*/
					  }
					  else
					  {
						 if(Srecord_FLASH_line==0)
						 {
							 Srecord_FLASH_line = 1;/*the FLASH line has received*/

							 NVM_Init();			/*the NVM (PFlash and FlexNVM) initialization can be put here for fast jump*/

							 RGB_GREEN_LED_On();                /* start flash erasing  */
							 erase_flash_except_bootloader();	/* erase the FLASH for data program*/
							 RGB_GREEN_LED_Off();               /* finish flash erasing   */
						 }

						 RGB_GREEN_LED_On();             /*start Flash program*/

						 SrcdAlign4W(&srcd);       		 /*align to 4 Word*/
						 SrcdProg_PFlash(&srcd);   		 /*program a line*/

						 RGB_GREEN_LED_Off();            /*finished Flash program*/
					  }
					}

					pSln = 0;                 /*reset the S-record line buffer pointer for new line receive*/
					StatusAck(UP_READY);      /*feed back ready for receive new data download*/

					break;

				case DOWN_FILE_END:           /* completed transmit of Srecord file   */
					StatusAck(UP_PRGEND);     /*feed back program end to PC terminal*/
					STATE=_STA_PRGEND;
					break;

				default:                             /* Srecord data received */
					for (i=0; i<CAN_RxMsg->length; i++)    /*the default line length of S-record generated by CodeWarrior IDE is 0x20(32) Bytes*/
					{                                /*so it needs 4 CAN frame to transmit*/
						  Sline[pSln++]=CAN_RxMsg->data[i]; /*store the CAN received data to S-record line buffer*/
					}
					  StatusAck(UP_READY);             /*feed back ready for receive new data download*/
					  break;
			}/*end if switch*/

			if(STATE==_STA_PRGEND)    /*P-Flash programmed OK*/
			{
				Prepare_Before_Jump();/*de-initialize the used peripherals and clean RAM*/
				app_entry();          /*jump to app and should not back */
				for(;;) ;			  /* stop here however in case run away */
			}
		}/*end of CAN_BufferReceive_Flag==1 if*/
    }

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.1 [05.21]
**     for the Freescale S32K series of microcontrollers.
**
** ###################################################################
*/
